package com.gzhu.knowledgeAdmin.service.impl;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gzhu.knowledgeAdmin.common.constant.OperatorType;
import com.gzhu.knowledgeAdmin.common.exception.BusinessException;
import com.gzhu.knowledgeAdmin.common.handler.KeywordImportHandler;
import com.gzhu.knowledgeAdmin.common.result.ErrorCode;
import com.gzhu.knowledgeAdmin.common.utils.UserInfoUtils;
import com.gzhu.knowledgeAdmin.common.vo.KeywordExportVo;
import com.gzhu.knowledgeAdmin.common.vo.PageVo;
import com.gzhu.knowledgeAdmin.entity.Condition;
import com.gzhu.knowledgeAdmin.entity.Operator;
import com.gzhu.knowledgeAdmin.entity.Rule;
import com.gzhu.knowledgeAdmin.service.ConditionService;
import com.gzhu.knowledgeAdmin.service.OperatorService;
import com.gzhu.knowledgeAdmin.service.RuleService;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import com.gzhu.knowledgeAdmin.dao.KeywordDao;
import com.gzhu.knowledgeAdmin.entity.Keyword;
import com.gzhu.knowledgeAdmin.service.KeywordService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;


import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;


@Service("keywordService")
public class KeywordServiceImpl extends ServiceImpl<KeywordDao, Keyword> implements KeywordService {

    @Autowired
    private OperatorService operatorService;

    @Autowired
    private RuleService ruleService;

    @Autowired
    private ConditionService conditionService;


    @Override
    public PageVo queryPage(Map<String, Object> params) {
        // 获取当前页和每页大小
        long pageNo = Long.parseLong((String) params.get("page"));
        long pageSize = Long.parseLong((String) params.get("limit"));
        String keyWord = (String) params.get("keywords");

        Page<Keyword> page = new Page<>(pageNo, pageSize);
        QueryWrapper<Keyword> wrapper = new QueryWrapper<>();

        if (!StringUtils.isEmpty(keyWord)) {
            wrapper.like("name", keyWord);
        }
        // 只能查询自己公司的
        String gsid = UserInfoUtils.getCurrentUser().getGsid();
        wrapper.eq("gsid", gsid);

        baseMapper.selectPage(page, wrapper);

        return new PageVo(page);
    }

    @Override
    public void saveKeyword(Keyword keyword) {

        // 获取公司id
        String gsid = UserInfoUtils.getCurrentUser().getGsid();
        keyword.setGsid(gsid);
        baseMapper.insert(keyword);
    }

    @Override
    @Transactional
    public String importKeyword(MultipartFile file) throws IOException {
        ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
        List<Keyword> all = reader.readAll(Keyword.class);

        // 获取公司id
        String gsid = UserInfoUtils.getCurrentUser().getGsid();

        KeywordImportHandler keywordImportHandler = new KeywordImportHandler(gsid, all);
        String msg = keywordImportHandler.handle();
        return msg;

    }


    @Override
    /**
     * 导出关键词库
     */
    public void exportKeyword(Map<String, Object> params, HttpServletResponse response) {
        ExcelWriter writer = null;
        ServletOutputStream outputStream = null;

        try {
            // 查询需要导出的所有数据
            String keyWord = (String) params.get("keywords");
            QueryWrapper<KeywordExportVo> wrapper = new QueryWrapper<>();

            if (!StringUtils.isEmpty(keyWord)) {
                wrapper.like("name", keyWord);
            }
            // 只能查询自己公司的
            String gsid = UserInfoUtils.getCurrentUser().getGsid();
            wrapper.eq("gsid", gsid);

            List<KeywordExportVo> keywordList = baseMapper.selectExportList(wrapper);

            // 导出
            String fileName = "关键词列表.xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));

            //创建xlsx格式的
            writer = ExcelUtil.getWriter(true);

            // 只输出拥有@Alias注解的属性
//        writer.setOnlyAlias(true);
            // 一次性写出内容，使用默认样式，强制输出标题
            writer.write(keywordList, true);

            //out为OutputStream，需要写出到的目标流
            outputStream = response.getOutputStream();
            writer.flush(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭writer，释放内存
            writer.close();

            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }

    @Override
    public void removeBatchByIds(List<Integer> ids) {

        Set<Integer> set = new HashSet<>(ids);

        checkedIfUsed(set);

        baseMapper.deleteBatchIds(ids);
    }

    @Override
    public void updateKeyword(Keyword keyword) {

        // 被引用的关键词不能被修改
        HashSet<Integer> hashSet = new HashSet<>();
        hashSet.add(keyword.getId());
        checkedIfUsed(hashSet);

        baseMapper.updateById(keyword);
    }

    private void checkedIfUsed(Set<Integer> set) {

        // 获取使用该公司的所有规则
        String gsid = UserInfoUtils.getCurrentUser().getGsid();
        List<Rule> ruleList = ruleService.list(new QueryWrapper<Rule>().eq("gsid", gsid));


        // 获取规则涉及到的条件id
        Set<Integer> conditionIdSet = new HashSet<>();
        for (Rule rule : ruleList) {
            List<Integer> conditionIdList = com.gzhu.knowledgeAdmin.common.utils.StringUtils.extractNumbers(rule.getContent());
           conditionIdSet.addAll(conditionIdList);
        }
        Collection<Condition> conditions = conditionService.listByIds(conditionIdSet);

        // 获取涉及到的所有算子id
        Set<Integer> operatorIdSet = new HashSet<>();
        for (Condition condition : conditions) {
            List<Integer> operatorIdList = com.gzhu.knowledgeAdmin.common.utils.StringUtils.extractNumbers(condition.getContent());
            operatorIdSet.addAll(operatorIdList);
        }


        // 获取所有算子
        List<Operator> operatorList = (List<Operator>) operatorService.listByIds(operatorIdSet);


        // 判断是否有被引用关键词，如果有，直接拒绝此次操作
        for (Operator operator : operatorList) {
            if(operator.getType()== OperatorType.CONTAIN_KEYWORD){
                String[] split = operator.getContent().split(",");
                for (String s : split) {
                    if(set.contains(Integer.parseInt(s))){
                        throw new BusinessException(ErrorCode.USED_ERROR);
                    }
                }
            }
        }

    }

}